home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Text⁄Files / Suntar 1.3.2 / folderStdfile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-31  |  23.4 KB  |  786 lines  |  [TEXT/KAHL]

  1. /*******************************************************************************\
  2.  
  3. customized standard file module
  4.  
  5. © March 1991 Gabriele Speranza
  6. modified 31 dec 1991, feb 92, apr 92
  7.  
  8. This program is public domain, feel free to use it or part of it for anything
  9.  
  10. \*******************************************************************************/
  11.  
  12. #include "system7.h"
  13. #include "PB_sync.h"
  14. #include "antiglue.h"
  15.  
  16. #include <string.h>
  17. #include "suntar.h"
  18. #include "windows.h"
  19.  
  20. #define SETDITL
  21. #define CLOSE_SF_WD
  22. #define DA_CANCEL     /* always force Cancel even when an Open would have the same effect */
  23.  
  24. short curr_vrefnum;
  25. extern unsigned char PNS[];
  26. extern Boolean gHasCustomPutFile;
  27. char *my_p2cstr();
  28. SFReply        reply;
  29. Point        where[7];
  30. static short n_open_WD=0;
  31. #define max_open_WD 20
  32. static short open_WD[max_open_WD];
  33. unsigned char*nomeFormato;
  34. Boolean SB3_compatibility=false;
  35.  
  36. #ifndef NULL
  37. #define NULL 0L
  38. #endif
  39. #define sfHookNullEvent 100
  40.  
  41. void set_DITL_title(short,unsigned char *);
  42.  
  43.  
  44. /************* routine per selezionare un file o directory ******************/
  45.  
  46. #define writeButton        11
  47. #define cancelButton    3
  48. #define openButton        1
  49.  
  50. static long        current_dir_ID;
  51. static short    current_val_OK;
  52.  
  53. static unsigned char string_1[]="\pSalva qui",
  54.     string_2[]="\pAnnulla",
  55.     string_3[]="\pEspelli",
  56.     string_4[]="\pUnità Disco",
  57.     string_5[]="\pgvu1h5%&#*√Æ@πå¥◊Ÿª",
  58.     /*string_5[]="\p\10\0\37";*/    /* an "impossible" file name: no more useful since
  59.         now I simulate a Cancel. Well, not exactly: AppleShare may see the name even 
  60.         when Cancel is simulated, hence there must be a name and it must not contain
  61.         "absurd" characters, otherwise you get a System Error */
  62.     string_6[]="\pApri",
  63.     string_7[]="\pOpen";
  64.  
  65. #define ESC 27
  66.  
  67. pascal Boolean SF_filter(DialogPtr,EventRecord*,short *);
  68. static pascal Boolean SF_filter(theDialog, theEvent, itemHit)
  69. DialogPtr theDialog;
  70. EventRecord* theEvent;
  71. short * itemHit;
  72. {
  73.  
  74. if(theEvent->what==nullEvent){
  75.     /* under System 7, the update events for windows below the System 6-like
  76.     standard file dialogs are not received if I don't explicitly ask for them.
  77.     I don't know whether it's a bug or an attempt to solve the problem described
  78.     in TN304, which for some reason believes that suntar belongs to the category
  79.     of programs which must be cheated.
  80.     System 7 is wonderful, but all its tricks are a damnation for programmers !
  81.     And they are not documented... and there is no way to tell to System 7 that
  82.     I know that I must behave well and I must not be cheated...
  83.     */
  84.     if(!EventAvail (updateMask,theEvent) )
  85.         return false;
  86.       }
  87. if(theEvent->what==updateEvt||theEvent->what==activateEvt){
  88.     /*SetPort(theEvent->message);*/
  89.     UpdateFilter(theEvent);
  90.     }
  91. else if(theEvent->what==keyDown){
  92.     short    kind;
  93.     Handle    h;
  94.     Rect    r;
  95.     if((unsigned char)theEvent->message==CR || (unsigned char)theEvent->message==enter_key){
  96.         GetDItem(theDialog,1,&kind,&h,&r);
  97.         SelectButton(h);
  98.         *itemHit=1;
  99.         return true;
  100.         }
  101.     else if((unsigned char)theEvent->message==ESC ||
  102.             (unsigned char)theEvent->message=='.'&&(theEvent->modifiers&cmdKey) ){
  103.         GetDItem(theDialog,3,&kind,&h,&r);        /* the Cancel button is item 3 in a
  104.                         get dialog, it's 2 in a put (and 3 is the prompt string, not
  105.                         a button) */
  106.         if(kind==ctrlItem+btnCtrl)
  107.             *itemHit= 3;
  108.         else
  109.             GetDItem(theDialog,(*itemHit= 2),&kind,&h,&r);
  110.         SelectButton(h);
  111.         return true;
  112.         }
  113.     }
  114. return false;
  115. }
  116.  
  117.  
  118. void my_SF_Put(prompt,fname)
  119. unsigned char *prompt,*fname;
  120. {
  121.     flush_all();
  122.     SFPPutFile(where[2],prompt,fname,NULL,&reply, -3999, SF_filter);
  123.     #ifdef CLOSE_SF_WD
  124.     if(reply.good) register_WD(reply.vRefNum);
  125.     #endif
  126. }
  127.  
  128. void my_SF_Get(numTypes,typeList)
  129. short numTypes;
  130. SFTypeList typeList;
  131. {
  132.     flush_all();
  133.     SFPGetFile(where[3],PNS,NULL,numTypes,typeList,NULL,&reply, -4000, SF_filter);
  134. #ifdef CLOSE_SF_WD
  135.     if(reply.good) register_WD(reply.vRefNum);
  136. #endif
  137. }
  138.  
  139.  
  140. pascal short file_or_folder_hook(short,DialogPtr);
  141. static pascal short file_or_folder_hook(item, theDialog)
  142.     short        item;
  143.     DialogPtr    theDialog;
  144. {
  145.     short    kind;
  146.     Handle    h;
  147.     Rect    r;
  148.     extern Boolean in_Italia;
  149.  
  150.     if(item==-1) {
  151. /* initialization: translate button titles to Italian */
  152.         if(in_Italia){
  153.             #ifndef SETDITL
  154.             GetDItem(theDialog,1,&kind,&h,&r);
  155.             SetCTitle(h,string_6);
  156.             #endif
  157.             GetDItem(theDialog,3,&kind,&h,&r);
  158.             SetCTitle(h,string_2);
  159.             GetDItem(theDialog,5,&kind,&h,&r);
  160.             SetCTitle(h,string_3);
  161.             GetDItem(theDialog,6,&kind,&h,&r);
  162.             SetCTitle(h,string_4);
  163.             GetDItem(theDialog,11,&kind,&h,&r);
  164.             SetCTitle(h,"\pScrivi");
  165.             GetDItem(theDialog,12,&kind,&h,&r);
  166.             SetIText(h,"\pScegli il file o cartella da archiviare");
  167.             }
  168.         GetDItem(theDialog,13,&kind,&h,&r);
  169.         SetIText(h,nomeFormato);
  170.         current_val_OK = false;
  171.         }
  172.     else if(item==writeButton){        /* file o directory selezionata*/
  173.         if (reply.fType != 0 || reply.fName[0]!=0) {
  174.         /* remember which folder was currently selected, if it was a folder */
  175.             current_dir_ID = reply.fType;    /* if the current selection is a folder,
  176.                         this field contains its dir ID */
  177.             current_val_OK = reply.fName[0]==0 ? 1 : -1;    /*cioè, solo se è una directory, non un file
  178.                          -- the name is NOT stored here if it was a folder (se IM vol IV) */
  179.             return cancelButton; /* 
  180.                     declare that the cancel button was pressed, remembering that 
  181.                     it's not so; for files, I could return openButton, but there is 
  182.                     a problem: if the selected file is an alias under System 7, 
  183.                     the alias is NOT resolved and a beep is done: I wish that 
  184.                     unresolved alias, but I don't wish that beep ! */
  185.             }
  186.         else
  187.             return sfHookNullEvent;    /* per dirgli di ignorare la cosa... non dovrebbe capitare comunque
  188.                         grazie al filtro di eventi che disabilita il bottone
  189.                         -- Really, the event filter disables the button when nothing
  190.                         is selected, so I should not receive "button pressed" items,
  191.                         but if I do, I ignore it */
  192.         }
  193.     return item;
  194. }
  195.  
  196. pascal Boolean file_or_folder_filter(DialogPtr,EventRecord*,short *);
  197. static pascal Boolean file_or_folder_filter(theDialog, theEvent, itemHit)
  198. DialogPtr theDialog;
  199. EventRecord* theEvent;
  200. short * itemHit;
  201. {
  202. short    kind;
  203. Rect    r;
  204. ControlHandle openH,writeH;
  205.  
  206. GetDItem(theDialog,openButton,&kind,&openH,&r);
  207. GetDItem(theDialog,writeButton,&kind,&writeH,&r);
  208. HiliteControl(writeH, (**openH).contrlHilite);    /* the write button is enabled/disabled
  209.             to follow the current state of the Open Button */
  210. return SF_filter(theDialog,theEvent,itemHit);
  211. }
  212.  
  213. short get_file_or_folder(s,n_types,myTypes)
  214. /* presents a modified file dialog which allows to choose either a file or
  215. a folder, with the extra "Write" button
  216. returns:
  217. -1 cancel
  218. 0 folder
  219. 1 file
  220. */
  221. Str255    s;
  222. short n_types;
  223. SFTypeList        *myTypes;
  224. {short i;
  225.  
  226.     flush_all();
  227. #ifdef SETDITL
  228.     set_DITL_title(200,in_Italia?string_6:string_7);
  229. #endif
  230.  
  231.     SFPGetFile(where[1],PNS,NULL,n_types,myTypes,file_or_folder_hook,&reply,
  232.         200,file_or_folder_filter);
  233.  
  234.     reply.fName[1+reply.fName[0]]=0;
  235.     if (current_val_OK>0){
  236.     /* write folder.
  237.     the vRefNum in the reply is not correct, but the low memory variable SFSaveDisk 
  238.     holds the negative of the right value */
  239. #ifdef V_122
  240.         if(i=PathNameFromDirID(current_dir_ID,(curr_vrefnum= -SFSaveDisk),s)) {
  241.             /* TN 238 sconsiglia di creare dei full path name, perché in A/UX i
  242.             full path name vogliono la '/' anche se si fanno chiamate alle routine
  243.             HFS del toolbox... */
  244.             SysBeep(5);
  245.             printf("Pathname error\n");
  246.             raise_error();
  247.             }
  248. #else
  249.         /* get the name of the folder */
  250.         {
  251.         CInfoPBRec    block;
  252.         Str255        directoryName;
  253.         OSErr err;
  254.  
  255.         block.dirInfo.ioNamePtr = &s[1];
  256.         block.dirInfo.ioDrParID = current_dir_ID;
  257.  
  258.         block.dirInfo.ioVRefNum = curr_vrefnum= -SFSaveDisk;
  259.         block.dirInfo.ioFDirIndex = -1;
  260.         block.dirInfo.ioDrDirID = block.dirInfo.ioDrParID;
  261.  
  262.         err = PBGetCatInfoSync(&block);
  263.         if(err!=noErr) error_message_1("Folder error %d\n",err);
  264.         if(current_dir_ID==2){        /* root directory, it's already a refnum... */
  265.             mcopy(s,&s[1],s[1]+1);    /* must not add a semicolon */
  266.             }
  267.         else{
  268.             WDPBRec param;
  269.             s[0] = s[1]+1;
  270.             s[1]=':';
  271.  
  272.             /* open a WD on the parent directory */
  273.  
  274.             param.ioVRefNum= curr_vrefnum;
  275.             param.ioNamePtr=NULL;
  276.             param.ioWDProcID=signature;
  277.             param.ioWDDirID= block.dirInfo.ioDrParID;
  278.             if(err=PBOpenWDSync(¶m)) error_message_1("Working directory error %d\n",err);
  279.             /* printf("selected=%d %ld %P\n",curr_vrefnum,block.dirInfo.ioDrParID,s); */
  280.             curr_vrefnum=param.ioVRefNum;
  281.             register_WD(param.ioVRefNum);
  282.             }
  283.         /* Append a Macintosh style colon (':') */
  284.         pStrcat(s,"\p:");
  285.         SetVol(NULL,curr_vrefnum);
  286.         }
  287. #endif
  288.         return 0;
  289.         }
  290.     if(current_val_OK<0){    /* write file */
  291.         WDPBRec param;
  292.         param.ioVRefNum= -SFSaveDisk;
  293.         param.ioNamePtr=NULL;
  294.         param.ioWDProcID=signature;
  295.         param.ioWDDirID=CurDirStore;
  296.         if(PBOpenWDSync(¶m)) error_message("Working directory error\n");
  297.         reply.vRefNum=param.ioVRefNum;    /* ad uso delle varie open...*/
  298.         register_WD(param.ioVRefNum);
  299.         }
  300.     else if(!reply.good)
  301.         return -1;    /* cancel */
  302.     /* if I am here, it was a open/write file */
  303.     SetVol(NULL,reply.vRefNum);    /* the old version of the program usually passed
  304.             0 as vrefnum relying on a SetVol, the new one prefers to pass explicitly
  305.             curr_vrefnum, but if we have forgotten to modify one call, doing
  306.             also the SetVol avoid troubles: one day all these SetVol will be
  307.             deleted, but then an accurate beta testing should follow... */
  308. #ifdef CLOSE_SF_WD
  309.     register_WD(reply.vRefNum);
  310. #endif
  311.     curr_vrefnum=reply.vRefNum;
  312.     pStrcpy(s,reply.fName);
  313.     return 1;
  314. }
  315.  
  316. /********** routines per la selezione di una directory di destinazione *********/
  317.  
  318. pascal short select_dir_hook (short,DialogPtr);
  319. static pascal short select_dir_hook (item, theDialog)
  320.  short item;
  321.  DialogPtr theDialog;
  322. {
  323.  
  324. if(item==-1 && in_Italia){
  325.     short    kind;
  326.     Handle    h;
  327.     Rect    r;
  328.     #ifndef SETDITL
  329.     GetDItem(theDialog,1,&kind,&h,&r);
  330.     SetCTitle(h,string_1);
  331.     #endif
  332.     GetDItem(theDialog,2,&kind,&h,&r);
  333.     SetCTitle(h,string_2);
  334.     GetDItem(theDialog,5,&kind,&h,&r);
  335.     SetCTitle(h,string_3);
  336.     GetDItem(theDialog,6,&kind,&h,&r);
  337.     SetCTitle(h,string_4);
  338.     }
  339. else if(item==1){    /* Save here */
  340.     current_val_OK=true;
  341.     #ifdef DA_CANCEL
  342.     return 2;    /* Cancel: hence, no risk to get a dialog "file existing, OK to replace ?" */
  343.     #endif
  344.     }
  345. return item;
  346. }
  347.  
  348. pascal Boolean select_dir_filter(DialogPtr,EventRecord*,short *);
  349. static pascal Boolean select_dir_filter(theDialog, theEvent, itemHit)
  350. DialogPtr theDialog;
  351. EventRecord* theEvent;
  352. short * itemHit;
  353. {
  354.  
  355. if(theEvent->what==keyDown||theEvent->what==autoKey){
  356.     theEvent->what=nullEvent;
  357.     }    /* se no si può cancellare il nome, e il bottone per
  358.                                 salvare viene disabilitato...
  359.                                 -- the file name can't be modified ! It will be ignored,
  360.                                 but if you delete it, the save button will be disabled,
  361.                                 and save here IS the save button */
  362. /* no, niente da fare, lo standard file non me li passa affatto
  363. -- useless, such events are not passed to my filter
  364. else if(theEvent->what==diskEvt){
  365.     unexpected_disk_insertion(theEvent->message);
  366.     theEvent->what=nullEvent;
  367.     }
  368. */
  369.  
  370. return SF_filter(theDialog, theEvent, itemHit);
  371. }
  372.  
  373. static Boolean need_update,is_outline;
  374.  
  375. pascal Boolean sys7_select_dir_filter(DialogPtr,EventRecord*,short *,Ptr);
  376. static pascal Boolean sys7_select_dir_filter(theDialog, theEvent, itemHit, myDataPtr)
  377. DialogPtr theDialog;
  378. EventRecord* theEvent;
  379. short * itemHit;
  380. Ptr myDataPtr;
  381. {
  382. if(theEvent->what==updateEvt && (DialogPtr)theEvent->message==theDialog)
  383.     need_update=true;
  384. return SF_filter(theDialog, theEvent, itemHit);
  385. }
  386.  
  387.  
  388. pascal short sys7_select_dir_hook(short,DialogPtr,Ptr);
  389. static pascal short sys7_select_dir_hook(item,theDialog,myDataPtr)
  390. short item;
  391. DialogPtr theDialog;
  392. Ptr myDataPtr;
  393. {
  394. /* it is correct to draw an outline to the "save here" button, however
  395. ther are two problems:
  396. 1) there is not a good place to do that: in the event filter, I could do that as an
  397.     answer to the update event, but it should be between BeginUpdate and EndUpdate,
  398.     or in the worst case after EndUpdate, while I'm called before. In my_modal
  399.     I handle the whole update by myself, but here doing that could cause 
  400.     incompatibility problems (if something is redrawn directly and not through
  401.     the redraw routine of a dialog item... for example, Boomerang's file info
  402.     disappear in case of an update). Hence I do that periodically, that's
  403.     NOT a good solution but I haven't found a better one
  404.     (probably the "Better" way is to install an user item for the outline...
  405.     maybe I'll try that one day)
  406. 2) The return and enter key mean "open" or "click on the default button"
  407.     according to what is currently selected (a folder/volume, or a file/nothing):
  408.     hence, I should outline the Save here button only when return means Save,
  409.     but the in StandardFileReply record only parID and vRefNum are updated, (the name,
  410.     sfIsFolder and sfIsVolume are updated only by Custom G E T file). Furthermore,
  411.     if the current volume is locked the Save button is dimmed, and must not be
  412.     outlined: this time, I should update things when the state change happens, that is
  413.     AFTER the handling of clicks on items which change the situation, but my
  414.     hook routine is called BEFORE the standard handling is performed: this time, a
  415.     periodic action looks like the only way to do things
  416. */
  417.  
  418. short    kind;
  419. ControlHandle    h;
  420. Rect    r;
  421. short i;
  422. ControlHandle saveH;
  423. /*
  424. StandardFileReply *sfrep=myDataPtr;
  425. printf("%d %d %ld %d %P\n",sfrep->sfIsFolder,sfrep->sfIsVolume,sfrep->sfFile.parID,
  426. sfrep->sfFile.vRefNum,sfrep->sfFile.name);
  427. */
  428.  
  429. if(((WindowPeek)theDialog)->refCon!='stdf') return item;
  430.  
  431. GetDItem(theDialog,1,&kind,&h,&r);
  432. GetDItem(theDialog,13,&kind,&saveH,&r);
  433. if((**h).contrlHilite!=(**saveH).contrlHilite)
  434.     HiliteControl(saveH, (**h).contrlHilite);    /* the save here button is 
  435.             enabled/disabled to follow the current state of the save Button */
  436. if(!(i=(**h).contrlHilite)){
  437.     char buffer[20];
  438.     GetCTitle(h,buffer);
  439.     i=strcmp("Save",my_p2cstr(buffer));    /* the "Open" string is chosen from the
  440.                                         system, depending on the nation, but the
  441.                                         Save string is from my resource... */
  442.     }
  443. if(i){    /* erase the outline */
  444.     /* probably it's possible to avoid all that by exploiting the calls described in
  445.     Technical Note 304, but beta testing of 1.2 has already started, it's too late to
  446.     try new routines */
  447.     if(is_outline){
  448.         Rect r1;
  449.         SetPort(theDialog);
  450.         r1.left=r.left-4;
  451.         r1.right=r.left;
  452.         r1.top=r.top-4;
  453.         r1.bottom=r.bottom+4;
  454.         EraseRect(&r1);
  455.         r1.left=r.right;
  456.         r1.right=r.right+4;
  457.         EraseRect(&r1);
  458.         r1.left=r.left;
  459.         r1.right=r.right;
  460.         r1.top=r.top-4;
  461.         r1.bottom=r.top;
  462.         EraseRect(&r1);
  463.         r1.top=r.bottom;
  464.         r1.bottom=r.bottom+4;
  465.         EraseRect(&r1);
  466.         }
  467.     is_outline=false;
  468.     }
  469. else{
  470.     if(!is_outline||need_update){
  471.         OutlineControl(saveH);
  472.         need_update=false;
  473.         }
  474.     is_outline=true;
  475.     }
  476.  
  477. if(item==-1&&in_Italia){
  478.     GetDItem(theDialog,13,&kind,&h,&r);
  479.     SetCTitle(h,string_1);
  480.     GetDItem(theDialog,2,&kind,&h,&r);
  481.     SetCTitle(h,string_2);
  482.     GetDItem(theDialog,5,&kind,&h,&r);
  483.     SetCTitle(h,string_3);
  484.     GetDItem(theDialog,6,&kind,&h,&r);
  485.     SetCTitle(h,"\pScrivania");
  486.     }
  487. else if(item==13){    /* Save here */
  488.     current_val_OK=true;
  489.     return 2;    /* Cancel */
  490.     }
  491. else if(item==1){    /* the Save button is out of screen,
  492.             but it's still the default button hence it's "pressed" by a return key */
  493.     GetDItem(theDialog,13,&kind,&h,&r);
  494.     SelectButton(h);
  495.     current_val_OK=true;
  496.     return 2;    /* Cancel */
  497.     }
  498. return item;
  499. }
  500.  
  501.  
  502.  
  503. void select_directory()
  504. {
  505. /* Presents a standard Put File where the save button is replaced by a "Save here"
  506. button and the filename box is not visible. The caller will ignore the name field
  507. in the reply record, using this routine to select the destination folder
  508. */
  509.     flush_all();
  510.     current_val_OK=false;
  511.     if(!gHasCustomPutFile || !useSys7_SF){
  512. #ifdef SETDITL
  513.         set_DITL_title(199,in_Italia?string_1:"\pSave here");
  514. #endif
  515.         SFPPutFile(where[0],PNS,
  516.             string_5,select_dir_hook,&reply,199,select_dir_filter);
  517. #ifndef DA_CANCEL
  518.         if(reply.good)
  519.             SetVol(NULL,curr_vrefnum=reply.vRefNum); /* setta la directory */
  520.         return;
  521. #endif
  522.         }
  523.     else{
  524.         /* the system 6 dialog is particularly annoying when used under system 7
  525.         (the "Save here" button is renamed open when a folder is selected) and
  526.         it's here that the new "new folder" button is more useful: hence the privilege
  527.         of being the only call to the standard file package done in the system 7 way */
  528.         StandardFileReply sfrep;
  529.         static short act_list[2]={1,7};
  530.         need_update=is_outline=false;
  531.         CustomPutFile(PNS,string_5,&sfrep,1043,where[4],sys7_select_dir_hook,
  532.             sys7_select_dir_filter, act_list,NULL, &sfrep);
  533.         reply.good=false;
  534.         }
  535.  
  536.     if(current_val_OK){
  537.         OSErr err;
  538. #define LOW_LEVEL_OWD
  539. #ifdef LOW_LEVEL_OWD
  540.         WDPBRec param;
  541.         param.ioVRefNum= -SFSaveDisk;
  542.         param.ioNamePtr=NULL;
  543.         param.ioWDProcID=signature;
  544.         param.ioWDDirID=CurDirStore;
  545.         err=PBOpenWDSync(¶m);
  546.         if(err){
  547.             error_message_1("Working directory error %d\n",err);
  548.             }
  549.         else
  550.             curr_vrefnum=param.ioVRefNum;
  551. #else
  552.         if((err=OpenWD(-SFSaveDisk,CurDirStore,0L,&curr_vrefnum))){
  553.             error_message_1("Working directory error %d\n",err);
  554.             }
  555. #endif
  556.  
  557.         register_WD(curr_vrefnum);
  558.  
  559.         SetVol(NULL,curr_vrefnum); /* setta la directory */
  560.         reply.vRefNum=curr_vrefnum;
  561.         reply.good=true;
  562.         }
  563. }
  564.  
  565. #define checkbox_state need_update    /* just to avoid using another variable */
  566.  
  567. pascal short checkbox_hook(short,DialogPtr);
  568. static pascal short checkbox_hook(item, theDialog)
  569.     short        item;
  570.     DialogPtr    theDialog;
  571. {
  572.     short    kind;
  573.     Handle    h;
  574.     Rect    r;
  575.     extern Boolean in_Italia;
  576.  
  577.     if(item==-1) {
  578. /* initialization: translate button titles to Italian */
  579.         GetDItem(theDialog,11,&kind,&h,&r);
  580.         SetCtlValue((ControlHandle)h,checkbox_state);
  581.         if(in_Italia){
  582.             SetCTitle(h,"\pscelta formato automatica");
  583.             #ifndef SETDITL
  584.             GetDItem(theDialog,1,&kind,&h,&r);
  585.             SetCTitle(h,string_6);
  586.             #endif
  587.             GetDItem(theDialog,3,&kind,&h,&r);
  588.             SetCTitle(h,string_2);
  589.             GetDItem(theDialog,5,&kind,&h,&r);
  590.             SetCTitle(h,string_3);
  591.             GetDItem(theDialog,6,&kind,&h,&r);
  592.             SetCTitle(h,string_4);
  593.             }
  594.         }
  595.     else if (item==11){
  596.         SetCheckBox(theDialog,item);
  597.         checkbox_state= ! checkbox_state;
  598.         }
  599.     return item;
  600. }
  601.  
  602. Boolean get_file_with_checkbox(ck_state)
  603. Boolean *ck_state;
  604. {
  605. SFTypeList        myTypes;
  606.  
  607. flush_all();
  608. checkbox_state=true;;
  609.  
  610. #ifdef SETDITL
  611. set_DITL_title(400,in_Italia?string_6:string_7);
  612. #endif
  613. SFPGetFile(where[5],PNS,NULL,-1,myTypes,checkbox_hook,&reply,
  614.         400, SF_filter);
  615.  
  616. if(reply.good){
  617. #ifdef CLOSE_SF_WD
  618.     register_WD(reply.vRefNum);
  619. #endif
  620.     *ck_state= checkbox_state;
  621.     }
  622. return reply.good;
  623. }
  624.  
  625. #define premuto_pausa need_update    /* just to avoid using another variable */
  626.  
  627. pascal short SFP_pausa_hook(short,DialogPtr);
  628. static pascal short SFP_pausa_hook(item, theDialog)
  629.     short        item;
  630.     DialogPtr    theDialog;
  631. {
  632.  
  633.     if(item==-1) {
  634. /* initialization: translate button titles to Italian */
  635.         if(in_Italia){
  636.             short    kind;
  637.             Handle    h;
  638.             Rect    r;
  639.  
  640.             #ifndef SETDITL
  641.             GetDItem(theDialog,1,&kind,&h,&r);
  642.             SetCTitle(h,"\pSalva");
  643.             #endif
  644.             GetDItem(theDialog,2,&kind,&h,&r);
  645.             SetCTitle(h,"\pNon salvare");
  646.             GetDItem(theDialog,5,&kind,&h,&r);
  647.             SetCTitle(h,string_3);
  648.             GetDItem(theDialog,6,&kind,&h,&r);
  649.             SetCTitle(h,string_4);
  650.             GetDItem(theDialog,9,&kind,&h,&r);
  651.             SetCTitle(h,"\pPausa");
  652.             }
  653.         }
  654.     else if (item==9){
  655.         premuto_pausa=true;
  656.         return 2; /* cancel...*/
  657.         }
  658.     return item;
  659. }
  660.  
  661.  
  662.  
  663. Boolean SFPut_con_pausa(fname,message)
  664. unsigned char *fname;
  665. char *message;
  666. {
  667. flush_all();
  668. premuto_pausa=false;
  669. #ifdef SETDITL
  670. set_DITL_title(399,in_Italia?"\pSalva":"\pSave");
  671. #endif
  672. SFPPutFile(where[6],message,fname,SFP_pausa_hook,&reply,399,SF_filter);
  673. if(premuto_pausa) return true;
  674.  
  675. #ifdef CLOSE_SF_WD
  676. if(reply.good) register_WD(reply.vRefNum);
  677. #endif
  678. return false;
  679. }
  680.  
  681.  
  682. /*********************************************************************/
  683.  
  684. #ifdef SETDITL
  685. static void set_DITL_title(id,title)
  686. short id;
  687. unsigned char *title;
  688. {
  689. /* System 7 changes the name of the "open" or "save" button to reflect the two
  690. different meanings (open a folder or select a file). In doing that, it forgets
  691. any SetCTitle and restores the title stored in the DITL: hence, the only way to
  692. change the title of those buttons at run time is to modify the DITL itself,
  693. an horribly dirty thing; really, in suntar the two strings usually happen to have
  694. the same size, but it's better not to exploit special cases
  695. */
  696. unsigned char **h,cur_l,new_l;
  697.  
  698. h = Get1Resource('DITL',id);
  699. if(h==NULL) return;
  700. HNoPurge (h);    /* modifying a resource in memory would be useless if it may be purged */
  701.  
  702. cur_l= (*(*h+15)+1)&~1;    /* the affected button is always item 1, hence I may
  703.                         use a fixed offset; otherwise, I should skip the previous
  704.                         items by adding their (size+1)&~1 to the pointer */
  705. new_l= (title[0]+1)&~1;
  706. if(cur_l != new_l){
  707.     Size s=GetHandleSize(h);
  708.     if(s<0) return;
  709.     if(new_l==cur_l)
  710.         ;
  711.     else if(new_l<cur_l){
  712.         BlockMove(*h+15+cur_l,*h+15+new_l,s-15-cur_l);
  713.         SetHandleSize (h,s+new_l-cur_l);
  714.         }
  715.     else{    /* new_l>cur_l */
  716.         SetHandleSize (h,s+new_l-cur_l);
  717.         BlockMove(*h+15+cur_l,*h+15+new_l,s-15-cur_l);
  718.         }
  719.     }
  720. pStrcpy(*h+15,title);
  721. if(new_l!=title[0]) *(*h+16+new_l)=0;
  722. }
  723. #endif
  724.  
  725. /*
  726.  Working directories must be closed: because there is a limited space,
  727. but above all because a folder in the trashcan can't be deleted when an
  728. open WD refers to it, causing an annoying dialog when doing an "empty trash".
  729. But there are some problems.
  730.   PBOpenWD does not create a WD if it already exists, but PBCloseWD closes it even 
  731. if it existed before the PBOpenWD, hence opening and closing it I might close a WD 
  732. which was already used and is still used by another part of the program. The 
  733. ioWDProcID field was meant to solve that problem, but under MultiFinder that field
  734. loses its original meaning.
  735.   TN 190 says that WDs created by standard file must NOT be closed, but it does
  736. not explain why, on the contrary there is that very good reason to close them.
  737.   By experimenting I discovered that:
  738. -) Under System 6 with MultiFinder, ioWDProcID is really ignored: if I open and
  739. close a WD on a folder already opened by standard file, the closeWD closes the
  740. WD created by standard file: hence, there should be no problem closing it anyway.
  741. -) Under System 7, ioWDProcID is used in the pre-Muultifinder way, and WDs created
  742. by standard file are marked 'ERIK', there is a way (nondocumented ?) so that a
  743. process identifier is stored together with ioWDProcID, so that different applications
  744. have a different set of WDs, in this situation it could be more dangerous to
  745. violate Apple rules and close the WDs created by standard file, but we've done
  746. that for a while without any problem.
  747. (To be safe, suntar 1.2.2 does not do that, but 1.3 and later version do).
  748.  
  749.  By now my solution is to remember the vrefnum and close it in the main command 
  750. loop (when no folder is been visited and no file is closed but going to be opened again).
  751.  However, SuperBoomerang 3 has some problems if I close a WD (even if I created
  752. it by OpenWD ! Remember that it could return a previously existing one ). The result
  753. is that in ANY case it's an error to close them and it's an error to leave them open.
  754.  People at Apple are not totally stupid, a different solution
  755. must exist: probably the only good solution would be NOT to create any WD but use PBH
  756. calls to exploit directly the triple information vrefnum-dirID-filename. But then,
  757. all standard file calls should be modified in order to avoid creating a WD 
  758. (that is using the System 7 calls when it's possible, since simulating a Cancel
  759. does not update the list of recently opened files kept by Boomerang) and
  760. I would be forbidden to perform even one non-PBH routine, a large part of
  761. the program should be carefully searched and modified... too much work.
  762. */
  763.  
  764.  
  765. void register_WD(n_WD)
  766. short n_WD;
  767. {
  768. register short i=0;
  769. /*printf("register %d\n",n_WD);*/
  770. while(i<n_open_WD)
  771.     if(n_WD==open_WD[i++]) return;
  772. if(n_open_WD<max_open_WD) open_WD[n_open_WD++]=n_WD;
  773. }
  774.  
  775. void close_all_open_WD()
  776. {
  777. short i;
  778. WDPBRec param;
  779. for(i=0;i<n_open_WD;i++){
  780.     param.ioVRefNum=open_WD[i];
  781.     /*printf("closeWD=%d\n",open_WD[i]);*/
  782.     if(!SB3_compatibility) PBCloseWDSync(¶m);
  783.     }
  784. n_open_WD=0;
  785. }
  786.